home *** CD-ROM | disk | FTP | other *** search
/ Developer Helper 1: Phil & Dave's Excellent CD / Excellent CD HFS.raw / Moof / Goodies / MPW Goodies / MPW Goodies⁄DTS / Srcs / Print2 Source / Print2.c next >
C/C++ Source or Header  |  1989-04-13  |  24KB  |  778 lines

  1. /*     Print2.c
  2.     MPW Tool to print two pages per page
  3.     Copyright Fred A. Huxham 1988
  4.     
  5.     Additional Options:
  6.     
  7.     -3                Flip page for 3-hole punched paper
  8.     
  9.     This tool supports the same printing options as the standard MPW Print tool
  10.     except for the following:
  11.     
  12.     -ff string        Form feed string.
  13.     -from n            Print pages starting from page number n.
  14.     -l[ines] n        Print (at most) n lines per page.
  15.     -ls n            Set line spacing.
  16.     -n                Turn on line numbering.
  17.     -nw                Width of the line number field in characters.
  18.     -page n            Number the pages of the file, beginning with n.
  19.     -q quality        Set print quality on the ImageWriter
  20.     -r                Output pages to the printer in reverse order.
  21.     -title name        If printing page headers, use name as the title.
  22.     -to n            Print pages up to page n.
  23.     -tm n            Top margin
  24.     -bm n            Bottom margin
  25.     -lm n            Left margin
  26.     -rm n            Right margin
  27.     
  28.     I didn't implement these options for two reasons:
  29.     
  30.     1. I don't use them.
  31.     2. I'm lazy.
  32.     
  33.     Revision History:
  34.     
  35.     07/14/88    FAH        File created
  36.     07/25/88    FAH        1.0A1 All the options that I ever use are complete.
  37.     07/26/88    FAH        Fixed a bug in DrawBorder where I wasn't checking to
  38.                         see if the user had selected the option to DrawHeaders or not.
  39.                         Created a routine, DoAbout so that multiple -p options would
  40.                         not cause the about string to be printed multiple times.
  41.     08/04/88    DJB        Various bug fixes, and added 3 Hole option (-3).
  42.     09/08/88    DJB        Fixed 3 Hole printing.
  43.                         Fixed overrun of Date/Time, Filename, Page Number in header
  44.                         Clear and restore FScaleDisable, for MPW 3.0b1
  45.                         Switched from TN#149 to jamming PrintRecord to set document name
  46.                         (Added 20% slack feature for Mercer)
  47.     09/16/88    DJB        Fixed bug in overrun of Date/Time, Filename, Page Number in header
  48.                         Set minimum font size to 3pt for Phil
  49.     
  50. */
  51. #define DEBUG
  52.  
  53. #include    <types.h>
  54. #include    <stdlib.h>
  55. #include    <stdio.h>
  56. #include    <fcntl.h>
  57. #include    <ioctl.h>
  58. #include    <cursorctl.h>
  59. #include    <quickdraw.h>
  60. #include    <resources.h>
  61. #include    <memory.h>
  62. #include    <files.h>
  63. #include    <string.h>
  64. #include    <strings.h>
  65. #include    <errmgr.h>
  66. #include    <errors.h>
  67. #include    <fonts.h>
  68. #include    <printtraps.h>
  69. #include    <packages.h>
  70. #include    <toolutils.h>
  71. #include    <osutils.h>
  72. #include    <ctype.h>
  73.  
  74. /*-------------------------------------------------------------------------------------------------*/
  75. /* Type definitions */
  76. typedef struct Header {
  77.     short    font;
  78.     short    size;
  79.     short    height;
  80.     Boolean    draw;
  81.     Boolean    modDate;
  82.     char    *title;
  83.     char    date[256];
  84.     char    time[256];
  85. } Header;
  86.  
  87. typedef struct Body {
  88.     short    font;
  89.     short    size;
  90.     short    tabWidth;
  91.     short    lineHeight;
  92.     short    linesPerPage;
  93.     short    borderType;
  94. } Body;
  95.  
  96. /* Globals */
  97. THPrint        thePrintRec;
  98. TPPrPort    thePrPort;
  99. Handle         jobNameH = nil;
  100. Header        theHeader;
  101. Body        theBody;
  102. short        numCopies = 1;
  103. short        cmdLineTab = 9999;
  104. short        cmdLineFont = 9999;
  105. short        cmdLineSize = 0;
  106. Boolean        printProgress = false;
  107. Boolean        threeHole = false;
  108. Boolean        slack = true;
  109. WindowPtr    phonyWindow = nil;
  110.  
  111. /* Enumeration constants */
  112. enum sides {left,right};
  113.  
  114. /* Defines */
  115. #define    maxStr    512
  116.  
  117. /* Function prototypes */
  118. void    SetDefaults();
  119. void    DoAbout();
  120. void     SetFileStuff(char *fileName);
  121. Rect    GetrPage(THPrint thePrintRec);
  122. void    ForceLandscape(THPrint thePrintRec);
  123. void    DrawHeader(Rect *theRect,short pageNum);
  124. Rect    DrawBorder(short whichSide,short pageNum);
  125. short    Tabs2Spaces(char *theString);
  126. OSErr    PrintFile(FILE *theStream);
  127. int        SetOptions(int argc, char *argv[],short *files);
  128. void    PrValidateAndName(THPrint tPR, char *fname);
  129. int        main(int argc, char *argv[]);
  130. /*-------------------------------------------------------------------------------------------------*/
  131.  
  132. /*-------------------------------------------------------------------------------------------------*/
  133. /* Set the default values for the globals */
  134. void SetDefaults()
  135. {
  136.     theHeader.font = times;
  137.     theHeader.size = 8;
  138.     theHeader.height = 0;
  139.     theHeader.draw = false;
  140.     
  141.     theBody.font = courier;
  142.     theBody.size = 6;
  143.     theBody.tabWidth = 4;
  144.     theBody.borderType = 0;
  145. }
  146. /*-------------------------------------------------------------------------------------------------*/
  147.  
  148. /*-------------------------------------------------------------------------------------------------*/
  149. /* Prints the about string to standard out (for the -p option) */
  150. void DoAbout()
  151. {
  152.     char    *about = "\nPrint2 (Version 1.0B1 September 8, 1988) - (c) 1988 Fred A. Huxham\n"
  153.                      "         (Modifications and minor bug fixes by  -  Dave Burnard)\n";
  154.  
  155.     fprintf(stdout,about);
  156.     fflush(stdout);
  157. }
  158. /*-------------------------------------------------------------------------------------------------*/
  159.  
  160. /*-------------------------------------------------------------------------------------------------*/
  161. /* This routine does a few different things.  First, set the header title to the
  162.     filename.  Then set the header date to either the file's last modification date/time
  163.     or the current date/time, depending on the theHeader.modDate flag.  Next, set the
  164.     font, size and tab values for the print job according to the following,
  165.         1.  Get the values from the command line.
  166.         2.  Get the values from the resource fork of the file (only if MPW text files)
  167.         3.  Use the defaults.
  168. */
  169. void SetFileStuff(char *fileName)
  170. {
  171.     unsigned long    temp, result;
  172.     long    temp1;
  173.     ParamBlockRec    thePB;
  174.     
  175.     theHeader.title = fileName;
  176.     
  177.     if(theHeader.modDate) {
  178.         thePB.fileParam.ioCompletion = 0;
  179.         thePB.fileParam.ioNamePtr = c2pstr(fileName);
  180.         thePB.fileParam.ioVRefNum = 0;
  181.         thePB.fileParam.ioFVersNum = 0;
  182.         thePB.fileParam.ioFDirIndex = 0;
  183.         if(!(PBGetFInfo(&thePB,false))) temp = thePB.fileParam.ioFlMdDat;
  184.         p2cstr(fileName);
  185.     } else GetDateTime(&temp);
  186.     IUDateString(temp,shortDate,theHeader.date);
  187.     IUTimeString(temp,false,theHeader.time);
  188.     
  189.     result = faccess(fileName,F_GFONTINFO,&temp1);
  190.     if(cmdLineFont != 9999) theBody.font = cmdLineFont;
  191.     else if(!result) theBody.font = HiWord(temp1);
  192.     if(cmdLineSize) theBody.size = cmdLineSize;
  193.     else if(!result >= 0) theBody.size = LoWord(temp1);
  194.  
  195.     if(cmdLineTab != 9999) theBody.tabWidth = cmdLineTab;
  196.     else if(!(faccess(fileName,F_GTABINFO,&temp1))) theBody.tabWidth = temp1;
  197.  
  198. }
  199. /*-------------------------------------------------------------------------------------------------*/
  200.  
  201. /*-------------------------------------------------------------------------------------------------*/
  202. /* Calculate and set various values having to do with lineHeight, linesPerPage, header height,
  203.     etc... */
  204.     
  205. #define GetFScaleDisable()    (*((char *) 0x0A63))
  206. void SetLineStuff()
  207. {
  208.     FontInfo    fInfo;
  209.     short        pageHeight;
  210.     Rect        tempRect;
  211.     Boolean        fscaledisable;
  212.     
  213.     if(theHeader.draw) {
  214.         TextFont(theHeader.font);
  215.         TextSize(theHeader.size);
  216.         GetFontInfo(&fInfo);
  217.         theHeader.height = fInfo.ascent + fInfo.descent + fInfo.leading + 4;
  218.     }
  219.     
  220.     fscaledisable = GetFScaleDisable();        /* Get state of font scaling flag */
  221.     SetFScaleDisable(false);                /* Enable font scaling so we get scaled lineheight */
  222.     
  223.     TextFont(theBody.font);
  224.     TextSize(theBody.size);
  225.     GetFontInfo(&fInfo);
  226.     theBody.lineHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
  227.     
  228.     SetFScaleDisable(fscaledisable);        /* Return to previous state of font scaling flag */
  229.  
  230.     tempRect = GetrPage(thePrintRec);
  231.     pageHeight = tempRect.bottom - tempRect.top - theHeader.height;
  232.     theBody.linesPerPage = pageHeight/theBody.lineHeight;
  233. }
  234. /*-------------------------------------------------------------------------------------------------*/
  235.  
  236. /*-------------------------------------------------------------------------------------------------*/
  237. /* Returns the rPage rectangle out of the print record. */
  238. Rect GetrPage(THPrint thePrintRec)
  239. {
  240.     Rect tempR;
  241.     
  242.     tempR = (**thePrintRec).prInfo.rPage;
  243.     if (threeHole) tempR.top += 15;
  244.     
  245.     return (tempR);
  246. }
  247. /*-------------------------------------------------------------------------------------------------*/
  248.  
  249. /*-------------------------------------------------------------------------------------------------*/
  250. /* This function takes the print record and forces it into landscape mode */
  251. /* This is sicker than sick.  It depends on the values of completely undocumented bits
  252.     of the print record.  This routine is subject to break at any point in time. */
  253. void ForceLandscape(THPrint thePrintRec)
  254. {
  255.     Rect    tempRect;
  256.     
  257.     /* If the portrait bit of the wDev field of the print record is set (bit 1), then
  258.         rotate the rPaper and rPage rectangles by 90 degrees and finally unset the
  259.         portrait bit to fake the print driver into thinking that the user has selected
  260.         landscape mode.  At the current time (July 1988) both the ImageWriter and 
  261.         LaserWriter use the same bit of the wDev for a portrait/landscape flag.
  262.         As long as this stays the same, this routine will work for both types of printers. */
  263.         
  264.     if((**thePrintRec).prStl.wDev & 0x0002) {
  265.         tempRect.top = (**thePrintRec).rPaper.left;
  266.         tempRect.left = (**thePrintRec).rPaper.top;
  267.         tempRect.bottom = (**thePrintRec).rPaper.right;
  268.         tempRect.right = (**thePrintRec).rPaper.bottom;
  269.         (**thePrintRec).rPaper = tempRect;
  270.         
  271.         tempRect.bottom = (**thePrintRec).prInfo.rPage.bottom;
  272.         (**thePrintRec).prInfo.rPage.bottom = (**thePrintRec).prInfo.rPage.right;
  273.         (**thePrintRec).prInfo.rPage.right = tempRect.bottom;
  274.         
  275.         (**thePrintRec).prInfoPT.rPage = (**thePrintRec).prInfo.rPage;
  276.         
  277.         (**thePrintRec).prStl.wDev ^= 0x0002;
  278.     }
  279.     
  280.     /*
  281.     **    Another completely skanky trick:
  282.     **
  283.     **    If 3-hole paper is used we need to rotate the paper 180 degrees
  284.     **  this is accomplished by setting the horizontal flip and vertical flip
  285.     **  bits in the printX[5] field of the PrintRecord
  286.     */
  287.     if (threeHole) {
  288.         (**thePrintRec).printX[5] |= 0x0006;
  289.     }
  290. }
  291. /*-------------------------------------------------------------------------------------------------*/
  292.  
  293. /*-------------------------------------------------------------------------------------------------*/
  294. /* Draw the page headers */
  295. void DrawHeader(Rect *theRect,short pageNum)
  296. {
  297.     short    oldFont,oldSize,titleWidth,dateWidth,pageWidth,pageCenter;
  298.     char    thePageStr[256];
  299.     
  300.     /* Save the current font and size settings */
  301.     oldFont = thePrPort->gPort.txFont;
  302.     oldSize = thePrPort->gPort.txSize;
  303.     
  304.     /* Set the header font and size and then draw the date/time value left justified */
  305.     TextFont(theHeader.font);
  306.     TextSize(theHeader.size);
  307.     MoveTo(theRect->left+4,theRect->top + theHeader.height-4);
  308.     DrawString(theHeader.date);
  309.     drawstring(" ");
  310.     DrawString(theHeader.time);
  311.     dateWidth = StringWidth(theHeader.date) + StringWidth(theHeader.time) + stringwidth(" ");
  312.     
  313.     /* Draw the page number right justified */
  314.     NumToString((long)pageNum,thePageStr);
  315.     pageWidth = StringWidth(thePageStr) + StringWidth("\pPage ");
  316.     MoveTo(theRect->right - 4 - pageWidth, theRect->top + theHeader.height-4);
  317.     DrawString("\pPage ");
  318.     DrawString(thePageStr);
  319.     
  320.     /* Draw the title centered over the document */
  321.     titleWidth = stringwidth(theHeader.title);
  322.     pageCenter = ((theRect->right - pageWidth - 4) + (theRect->left + dateWidth + 4))/2;
  323.     
  324.     if (titleWidth + pageWidth + dateWidth > theRect->right - theRect->left - 16)
  325.     {
  326.         char tmp_str[256];
  327.         char *first_colon, *last_colon;
  328.         
  329.         first_colon = strchr(theHeader.title, ':');
  330.         last_colon = strrchr(theHeader.title, ':');
  331.         
  332.         if (first_colon != nil && first_colon != last_colon) {
  333.             strncpy(tmp_str, theHeader.title, first_colon - theHeader.title + 1);
  334.             tmp_str[first_colon - theHeader.title + 1] = '\0';
  335.             
  336.             strcat(tmp_str, " ... ");
  337.             strcat(tmp_str, last_colon);
  338.             strcpy(theHeader.title, tmp_str);
  339.             titleWidth = stringwidth(theHeader.title);
  340.         }
  341.     }
  342.     MoveTo(pageCenter - (titleWidth>>1),theRect->top + theHeader.height-4);
  343.     drawstring(theHeader.title);
  344.     
  345.     /* Restore the old font and size settings */
  346.     TextFont(oldFont);
  347.     TextSize(oldSize);
  348. }
  349. /*-------------------------------------------------------------------------------------------------*/
  350.  
  351. /*-------------------------------------------------------------------------------------------------*/
  352. /* Draw the page border.  This routine draw either the right or left page border on the paper.
  353.     The border styles are the same as the standard MPW print tool.  Within this routine we also
  354.     draw the page header (if that option has been specified) */
  355. Rect DrawBorder(short whichSide,short pageNum)
  356. {
  357.     Rect    tempRect;
  358.     
  359.     tempRect = GetrPage(thePrintRec);
  360.     ClipRect(&tempRect);
  361.     if(whichSide == left) tempRect.right = ((tempRect.right-tempRect.left) >> 1) - 1;
  362.     if(whichSide == right) tempRect.left = ((tempRect.right-tempRect.left) >> 1) + 1;
  363.     tempRect.bottom -= 1;
  364.     if(theHeader.draw) DrawHeader(&tempRect,pageNum);
  365.     switch(theBody.borderType) {
  366.         case 0:
  367.             if(theHeader.draw) tempRect.top += theHeader.height;
  368.             break;
  369.         case 1:
  370.             FrameRoundRect(&tempRect,10,10);
  371.             if(theHeader.draw) {
  372.                 MoveTo(tempRect.left,tempRect.top+theHeader.height);
  373.                 LineTo(tempRect.right-1,tempRect.top+theHeader.height);
  374.                 tempRect.top += theHeader.height;
  375.             }
  376.             break;
  377.         case 2:
  378.             if(theHeader.draw) tempRect.top += theHeader.height;
  379.             FrameRoundRect(&tempRect,10,10);
  380.             break;
  381.     }
  382.     return(tempRect);
  383. }
  384. /*-------------------------------------------------------------------------------------------------*/
  385.  
  386. /*-------------------------------------------------------------------------------------------------*/
  387. /* This routine takes a C string, and then goes through it character by character looking for
  388.     tab characters (0x09).  When it finds one, it figures out how many space characters (0x20)
  389.     should be inserted for that tab.  Two strings are used in this routine, the original, and
  390.     a temporary one, into which the original, and the substituted space characters are copied.
  391.     When the end of the original string is reached, the temp string is copied over the original. */
  392. short Tabs2Spaces(char *theString)
  393. {
  394.     char    tempStr[maxStr];
  395.     char    *inStr,*outStr;
  396.     short    i,chars,spacesToInsert;
  397.     
  398.     inStr = theString;
  399.     outStr = tempStr;
  400.     chars = 0;
  401.  
  402.     while(*inStr != 0x00) {
  403.         if(*inStr == 0x09) {
  404.             inStr++;
  405.             spacesToInsert = theBody.tabWidth - (chars % theBody.tabWidth);
  406.             chars += spacesToInsert;
  407.             for(i=1;i<=spacesToInsert;i++) *outStr++ = 0x20;
  408.         } else {
  409.             *outStr++ = *inStr++;
  410.             chars++;
  411.         }
  412.     }
  413.     *outStr = 0x00;
  414.     strcpy(theString,tempStr);
  415.     return(chars);
  416. }
  417. /*-------------------------------------------------------------------------------------------------*/
  418.  
  419. /*-------------------------------------------------------------------------------------------------*/
  420. /* This routine prints the specified file. */
  421. OSErr PrintFile(FILE *theStream)
  422. {
  423.     Rect        drawRect;
  424.     short        pageSide,i;
  425.     char        tempStr[maxStr];
  426.     Boolean        done = false;
  427.     OSErr        result = noErr;
  428.     short        pageNum = 0;
  429.     long        totalChars = 0;
  430.     long        totalLines = 0;
  431.  
  432.     /* Open a printing grafPort */
  433.     thePrPort = PrOpenDoc(thePrintRec,nil,nil);
  434.     if(!(result = PrError())) {
  435.         SetLineStuff();
  436.         TextFont(theBody.font);
  437.         TextSize(theBody.size);
  438.                     
  439.         /* While we haven't reached the end of the file... */
  440.         while(!done) {
  441.             PrOpenPage(thePrPort,nil);
  442.             if(!(result = PrError())) {
  443.             
  444.                 /* Draw the left and right side of each piece of paper */
  445.                 for(pageSide=left;pageSide<=right && !done;pageSide++) {
  446.                     SpinCursor(1);
  447.                     drawRect = DrawBorder(pageSide,++pageNum);
  448.                     ClipRect(&drawRect);
  449.                     for(i=1;i<theBody.linesPerPage && !done;i++) {
  450.                         MoveTo(drawRect.left+3,drawRect.top+(i*theBody.lineHeight));
  451.                         if(fgets(tempStr,maxStr,theStream)) {
  452.                             totalChars += Tabs2Spaces(tempStr);
  453.                             totalLines ++;
  454.                             drawstring(tempStr);
  455.                         }
  456.                         else done = true;
  457.                     }
  458.                 }
  459.             }
  460.             PrClosePage(thePrPort);
  461.         }
  462.     } else {
  463.         fprintf(stderr,"### Print2 - PrOpenDoc fails, you lose.\n");
  464.         result = 3;
  465.         return (result);
  466.     }
  467.     PrCloseDoc(thePrPort);
  468.     if(printProgress) {
  469.         fprintf(stdout,"Printing \"%s\"... %d characters; %d lines; %d page(s) \n",
  470.         theHeader.title,totalChars,totalLines,pageNum);
  471.         fflush(stdout);
  472.     }
  473.     return(result);
  474. }
  475. /*-------------------------------------------------------------------------------------------------*/
  476.  
  477. /*-------------------------------------------------------------------------------------------------*/
  478. /* This routine takes argc and argv and sets all the options specified on the command line. */
  479. int SetOptions(int argc, char *argv[],short *files)
  480. {
  481.     short    argNum,stemp;
  482.     long    length;
  483.     int        status,temp;
  484.     char    *badOpt = "### %s - \"%s\" is not a valid option\n";
  485.     char    *badVal = "### %s - Usage error: %s %s (invalid value)\n";
  486.     
  487.     for(argNum=1;argNum<argc;argNum++) {
  488.         length = strlen(argv[argNum]);
  489.         if(*argv[argNum] != '-') argv[++(*files)] = argv[argNum];
  490.         else switch(tolower(*(argv[argNum]+1))) {
  491.         
  492.             /* Three hole paper? */
  493.             case '3':
  494.                 if(length == 2) threeHole = true;
  495.                 else {
  496.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  497.                     status = 1;
  498.                 }
  499.                 break;
  500.             
  501.             /* Border style */
  502.             case 'b':
  503.                 if(length == 2) theBody.borderType = 1;
  504.                 else if(length == 3 && (*(argv[argNum]+2)) == '2') theBody.borderType = 2;
  505.                 else {
  506.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  507.                     status = 1;
  508.                 }
  509.                 break;
  510.             
  511.             /* Number of copies */
  512.             case 'c':
  513.                 if(length == 2 || (length == 7 && !(strcmp(argv[argNum],"-copies")))) {
  514.                     temp = atol(argv[++argNum]);
  515.                     if(temp >= 1 && temp <= 100) numCopies = temp;
  516.                     else {
  517.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  518.                         status = 1;
  519.                     }
  520.                 } else {
  521.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  522.                     status = 1;
  523.                 }
  524.                 break;
  525.                 
  526.             /* Font to use */    
  527.             case 'f':
  528.                 if(length == 2 || (length == 5 && !(strcmp(argv[argNum],"-font")))) {
  529.                     getfnum(argv[++argNum],&cmdLineFont);
  530.                     if(!cmdLineFont) {
  531.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  532.                         status = 1;
  533.                     }
  534.                 } else {
  535.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  536.                     status = 1;
  537.                 }
  538.                 break;
  539.                 
  540.             /* Print headers (-h), header font (-hf[ont]), and header size (-hs[ize]) */    
  541.             case 'h':
  542.                 if(length == 2) theHeader.draw = true;
  543.                 else 
  544.                 if((length == 3 && (*(argv[argNum]+2)) == 'f') ||
  545.                    (length == 6 && !(strcmp(argv[argNum],"-hfont")))) {
  546.                     getfnum(argv[++argNum],&stemp);
  547.                     if(stemp) theHeader.font = stemp;
  548.                     else {
  549.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  550.                         status = 1;
  551.                     }
  552.                 }
  553.                 else 
  554.                 if((length == 3 && (*(argv[argNum]+2)) == 's') ||
  555.                    (length == 6 && !(strcmp(argv[argNum],"-hsize")))) {
  556.                     temp = atol(argv[++argNum]);
  557.                     if(temp > 2 && temp < 37) theHeader.size = temp;
  558.                     else {
  559.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  560.                         status = 1;
  561.                     }
  562.                 } else {
  563.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  564.                     status = 1;
  565.                 }
  566.                 break;
  567.                 
  568.             /* Use modification date in header (rather than current date) */
  569.             case 'm':
  570.                 if(length == 3 && (*(argv[argNum]+2)) == 'd') theHeader.modDate = true;
  571.                 else {
  572.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  573.                     status = 1;
  574.                 }
  575.                 break;
  576.                 
  577.             /* Allow the "slacker" to redeem himself */
  578.             case 'n':
  579.                 if(length == 8 && !(strcmp(argv[argNum],"-noslack"))) {
  580.                     slack = false;
  581.                 } else {
  582.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  583.                     status = 1;
  584.                 }
  585.                 break;
  586.                 
  587.             /* Write progress information */
  588.             case 'p':
  589.                 if(length == 2) {
  590.                     printProgress = true;
  591.                 } else {
  592.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  593.                     status = 1;
  594.                 }
  595.                 break;
  596.                 
  597.             /* Set the body font size */
  598.             case 's':
  599.                 if(length == 2 || (length == 5 && !(strcmp(argv[argNum],"-size")))) {
  600.                     temp = atol(argv[++argNum]);
  601.                     if(temp > 2 && temp < 37) cmdLineSize = temp;
  602.                     else {
  603.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  604.                         status = 1;
  605.                     }
  606.                 } else {
  607.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  608.                     status = 1;
  609.                 }
  610.                 break;
  611.                 
  612.             /* Set the tab width */
  613.             case 't':
  614.                 if(length == 2 || (length == 5 && !(strcmp(argv[argNum],"-tabs")))) {
  615.                     temp = atol(argv[++argNum]);
  616.                     if(temp >= 0 && temp <= 16) cmdLineTab = temp;
  617.                     else {
  618.                         fprintf(stderr,badVal,argv[0],argv[0],argv[argNum-1]);
  619.                         status = 1;
  620.                     }
  621.                 } else {
  622.                     fprintf(stderr,badOpt,argv[0],argv[argNum]);
  623.                     status = 1;
  624.                 }
  625.                 break;
  626.                 
  627.             /* A bad (non-supported) option */
  628.             default:
  629.                 fprintf(stderr,badOpt,argv[0],argv[argNum]);
  630.                 status = 1;
  631.                 break;
  632.         }
  633.     }
  634.     return(status);
  635. }
  636.  
  637. /*
  638. ** Skank to get print manager to use document name (TN #149)
  639. */
  640. void
  641. PrValidateAndName(THPrint tPR, char *fname)
  642. {
  643. #if 0
  644.     Rect r;
  645.     
  646.     if (phonyWindow != nil) DisposeWindow(phonyWindow);
  647.     phonyWindow = nil;
  648.     
  649.     SetRect(&r, 32000, 32000, 32010, 32010); /* Pretty far off-screen */
  650.     phonyWindow = newwindow(nil, &r, fname, true, plainDBox, (WindowPtr) -1, false, nil);
  651.  
  652.     PrValidate(tPR);
  653.     
  654.     if (phonyWindow != nil) DisposeWindow(phonyWindow);
  655.     phonyWindow = nil;
  656.     
  657. #else
  658.  
  659.     char   *username, *jobName;
  660.     char   tmp[256];
  661.     
  662.     /* 
  663.     **    Special treatment for the slacker (once in a while...(20%))
  664.     */
  665.     username = getenv("User");
  666.     if (slack && username != nil && !strcmp(username, "Paul Mercer") && (TickCount()%5 == 0) ) {
  667.         strcpy(tmp, "SLACKER! ");
  668.         strcat(tmp, fname);
  669.     } else {
  670.         strcpy(tmp, fname);
  671.     }
  672.     c2pstr(tmp);
  673.     jobName = tmp;
  674.  
  675.     if (jobNameH != nil) DisposHandle(jobNameH);
  676.     
  677.     /*
  678.     **    Another completely skanky trick:
  679.     **
  680.     **    Jam the PrintRecord with our jobName
  681.     **    this is accomplished by placing a handle to the 
  682.     **  name in the printX[3] and [4] fields of the PrintRecord
  683.     **
  684.     **    This is sicker than sick.  It depends on the values of 
  685.     **    completely undocumented bits of the print record.
  686.     **
  687.     **    This routine is subject to break at any point in time.
  688.     **
  689.     **    If anything fails, just fall through
  690.     */
  691.     jobNameH = NewString(jobName);
  692.     if (jobNameH != nil) {
  693.         *((Handle *) &(*tPR)->printX[3]) = jobNameH;
  694.     }
  695.     
  696.     PrValidate(tPR);
  697.     
  698. #endif
  699. }
  700.  
  701. /*-------------------------------------------------------------------------------------------------*/
  702.  
  703. /*-------------------------------------------------------------------------------------------------*/
  704. /* The main routine of the tool. */
  705. int main(int argc, char *argv[])
  706. {
  707.     short    argNum,files,i;
  708.     FILE    *theStream;
  709.     char    errorBuffer[256];
  710.     int        status;
  711.  
  712.     files = 0;
  713.     InitGraf(&qd.thePort);
  714.     InitCursorCtl(nil);
  715.     SetDefaults();
  716.     status = SetOptions(argc,argv,&files);
  717.     if(printProgress) DoAbout();
  718.     
  719.     if(!(thePrintRec = (THPrint)NewHandle(sizeof(TPrint)))) {
  720.         fprintf(stderr,"### %s - Unable to allocate a print record \n", argv[0]);
  721.         fprintf(stderr,"# %s\n", GetSysErrText(MacOSErr,errorBuffer));
  722.         status = 3;
  723.     }
  724.     else {
  725.         PrOpen();
  726.         if(PrError() != 0) {
  727.             fprintf(stderr,"### %s - PrOpen fails, check that a printer is selected.\n", argv[0]);
  728.             DisposHandle((Handle) thePrintRec);
  729.             status = 3;
  730.             return (status);
  731.         }
  732.         if(files == 0) {
  733.             if(ioctl(fileno(stdin),FIOINTERACTIVE,nil)) 
  734.                 for(i=1;i<=numCopies;i++) {
  735.                     PrintDefault(thePrintRec);
  736.                     ForceLandscape(thePrintRec);
  737.                     
  738.                     /*
  739.                     ** Validate and Set Document Name
  740.                     */
  741.                     PrValidateAndName(thePrintRec, "Dev:Stdin");
  742.                     
  743.                     PrintFile(stdin);
  744.                 }
  745.             else {
  746.                 fprintf(stderr,"### %s - Cannot print input from the console\n", argv[0]);
  747.                 status = 2;
  748.             }
  749.         } else {
  750.             for(argNum=1;argNum<=files;argNum++) {
  751.                 if(theStream = fopen(argv[argNum],"r")) {
  752.                 
  753.                     PrintDefault(thePrintRec);
  754.                     SetFileStuff(argv[argNum]);
  755.  
  756.                     ForceLandscape(thePrintRec);
  757.                     
  758.                     /*
  759.                     ** Validate and Set Document Name
  760.                     */
  761.                     PrValidateAndName(thePrintRec, argv[argNum]);
  762.                     
  763.                     for(i=1;i<=numCopies;i++) PrintFile(theStream);
  764.                     fclose(theStream);
  765.                 } else {
  766.                     fprintf(stderr,"### %s - Unable to open the file: \"%s\"\n", argv[0], argv[argNum]);
  767.                     fprintf(stderr,"# %s\n", GetSysErrText(MacOSErr,errorBuffer));
  768.                     status = 2;
  769.                 }
  770.             }
  771.         }
  772.         PrClose();
  773.         DisposHandle((Handle) thePrintRec);
  774.     }
  775.     return(status);
  776. }
  777. /*-------------------------------------------------------------------------------------------------*/
  778.